package com.coco.seck.schedulingutil;

import com.coco.common.constant.Constant;
import com.coco.seck.mapper.DeployMapper;
import com.coco.seck.mapper.SeckillGoodsMapper;
import com.coco.seck.pojo.TbDeploy;
import com.coco.seck.pojo.TbSeckillGoods;
import com.coco.seck.vo.MqDeployVo;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.redisson.Redisson;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.config.TriggerTask;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;

/**
 * @author HanSama
 * @date 2021年07月18日 10:14
 */
@Component
@EnableScheduling
public class CheckSeckillScheduling implements SchedulingConfigurer {

    /**
     *定时检查商品 每小时
     */
    private String goodsCron = "0 0 * * * ?";

    /**
     *每天晚上11点
     */
    private String orderCron = "0 5 * * * ?";

    @Autowired
    private DeployMapper deployMapper;
    @Autowired
    private SeckillGoodsMapper seckillGoodsMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    public void setOrderCron(String orderCron) {
        this.orderCron = orderCron;
    }

    public void setGoodsCron(String goodsCron) {
        this.goodsCron = goodsCron;
    }

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {


        /**
         *配置定时任务线程池
         * 保证定时任务 多线程执行
         */
        ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
        taskScheduler.setPoolSize(6);
        taskScheduler.initialize();
        taskRegistrar.setTaskScheduler(taskScheduler);


        /**
         * 使用JDK 1.8的Lambda表达式
         * 提前一个小时去数据库查看 将要秒杀的商品
         * 将商品id 和 商品库存  存入Redis
         * 任务内容.拉姆达表达式
         */
        TriggerTask addReidsGoods = new TriggerTask(
                () -> {
                    //获取提前一个小时的秒杀商品模板
                    List<TbDeploy> deployList = deployMapper.findDeployListBeforOneHour();
                    if (deployList!=null && deployList.size()>0){
                        //将模板下的秒杀商品加入Redis
                        deployList.forEach(deploy ->{
                            List<TbSeckillGoods> seckillGoodsList = seckillGoodsMapper.findOneByDeployId(deploy.getId());
                            seckillGoodsList.forEach(tbSeckillGoods -> {
                                System.out.println("提前1小时将即将秒杀的商品加入Redis  Lambda表达式，执行定时任务: " + new Date());
                                //向RabbitMQ发送消息
                                rabbitTemplate.convertAndSend(Constant.RabbitMqKeyConstant.ADD_REDIS_KILL_GOODS_KEY,"",new MqDeployVo(deploy,tbSeckillGoods));
                            });
                        });
                    }
                    },
                // 设置触发器，这里是一个拉姆达表达式，传入的TriggerContext类型，返回的是Date类型
                triggerContext -> {
                    //返回执行周期(Date)
                    return new CronTrigger(goodsCron).nextExecutionTime(triggerContext);
                });

        taskRegistrar.addTriggerTask(addReidsGoods);





        /**
         *定时检查秒杀成功商品 和 秒杀成功用户
         * 检查时间  整点过5分
         * 取出Redis信息  创建Order订单  清空Redis商品相关数据
         */
        TriggerTask addReidsOrder = new TriggerTask( // 任务内容.拉姆达表达式
                () -> {
                    //执行逻辑
                    System.out.println("检查Reids中秒杀的商品 将商品数量同步到MySQL   Lambda表达式，执行定时任务: " + new Date());
                    //获取已过期的秒杀模板信息
                    List<TbDeploy> deployList = deployMapper.findDeployListAfterFiveMinute();
                    //通过模板信息获取到 相关的已过秒杀时段 但未过期的秒杀商品
                    deployList.forEach(deploy -> {
                        List<TbSeckillGoods> seckillGoodsList =  seckillGoodsMapper.findSeckGoodsWithTimeOut(deploy.getId());

                        seckillGoodsList.forEach(tbSeckillGoods -> {
                            //向RabbitMQ发送消息
                            rabbitTemplate.convertAndSend(Constant.RabbitMqKeyConstant.SEC_GOODS_NUM_KEY,"",tbSeckillGoods);
                        });

                    });

                },
                // 设置触发器，这里是一个拉姆达表达式，传入的TriggerContext类型，返回的是Date类型
                triggerContext -> {
                    //返回执行周期(Date)
                    return new CronTrigger(orderCron).nextExecutionTime(triggerContext);
                });

        taskRegistrar.addTriggerTask(addReidsOrder);

    }

    }

